20,173 Matching Annotations
  1. Feb 2021
    1. The CTRL-\ key sends a kill signal to the foreground job which, under normal circumstances, is guaranteed to terminate it. This signal cannot be captured by a process. However, this means the process cannot cleanup and is just summarily stopped. In some cases, a process can be stuck in a kernel wait state so this signal never reaches it. In that case, the process is unusable but cannot be killed.
    1. This didn't work for me. Answering "y" somehow causes the script to finish immediately, rather than letting children continue sleeping. (Same thing if I make the signal handler function an empty no-op.) Does anyone know why it doesn't work for me or how to get it to work? It's as if the interrupt gets propagated to the child processes too so that it's no longer waiting for them.
    2. Also, this code will fail if $$ is not the process group leader, such as when the script is run under strace. Since a call to setsid(2) is probably tricky from a shell script, one approach might be to ps and obtain the process group ID from that.
    3. you really need #!/bin/sh -m for correct behavior of nested subshells. fg, bg, and wait wont work correctly otherwise
    4. ps -o pid,pgid,stat,args
    5. When your script starts a process, that child becomes a member of a process group with PGID equal to the PID of the parent process which is $$ in the parent shell.
    6. To accomplish this, after starting the children (loop.sh) in the background, call wait, and upon receipt of the INT signal, kill the process group whose PGID equals your PID.
    7. read -rep $'\nDo you wish to stop playing?(y/n)' yn
    8. You also need job controlled -monitoring in your parent so it keep track of its children. wait, for example, only works at all with job control. -monitor mode is how shells interact with terminals.
    9. You need a trap in loop.sh. Traps are cleared for every subshell started unless they are explicitly trap ''SIG ignored by the parent.
    10. so again, what, precisely, is false? Do you deny that a Control+C goes to the foreground process group?
    11. what, pray tell, is false in my examples? I am curious, so please be precise.
    1. Remove your last "just in case" trap, and the script should work fine also with the EXIT traps. INT in the trap calling the cleanup should be the correct way to deal with the interrupts, however
    2. How about just having all the output from point X be redirected to tee without having to repeat it everywhere and mess with all the sub-shells and execs
    3. exec > >(exec tee -a $logfile) 2>&1
    4. Can you be more specific about the "weird version of bash" ? In some situations (when run as /bin/sh) it runs n Posix compatibility mode ... If this is the case add set +o posix prior to exec
    5. The idea of the script is this: most of the important logic runs in a subshell which is piped through tee and to a logfile, so I don't have to tee every single line of the main logic to get it all logged.
    6. The rsync and sleep commands (the sleep is just an example) are run through exec to prevent the creation of zombie processes if I kill the parent script while they're running, and each potentially-long-running command is wrapped in its own subshell so that when exec finishes, it won't terminate the whole script.
    1. The parentheses always start a subshell. What's happening is that bash detects that sleep 5 is the last command executed by that subshell, so it calls exec instead of fork+exec. The sleep command replaces the subshell in the same process.
    1. Help defend Monica from defamation! Stack Overflow, Inc. must repair the damage caused by their libel against Monica Cellio, cooperate with the community, be willing to talk, treat users with respect, learn about the world outside the United States, open the governance of the sites.
    1. There's a bash debugger, bashdb, which is an installable package on many distros. It uses bash's built-in extended debugging mode (shopt -s extdebug).
    1. ps --forest -o pid,tty,stat,time,cmd -g $(ps -o sid= -p 2795)
    2. To get all the processes spawned by a process the whole tree needs to be built. I used awk for that. At first it builds a hash array to contain all PID => ,child,child... . At the end it calls a recursive function to extract all the child processes of a given process. The result is passed to another ps to format the result.
    3. This is in fact where I started, but this gives me all processes, which is exactly what I don't want.
    1. time run_with_timeout 3 sleep_and_exit 1 7; echo $?
    2. # Usage: run_with_timeout N cmd args... # or: run_with_timeout cmd args... # In the second case, cmd cannot be a number and the timeout will be 10 seconds. run_with_timeout () { local time=10 if [[ $1 =~ ^[0-9]+$ ]]; then time=$1; shift; fi # Run in a subshell to avoid job control messages ( "$@" & child=$! # Avoid default notification in non-interactive shell for SIGTERM trap -- "" SIGTERM ( sleep $time kill $child 2> /dev/null ) & wait $child ) }
    3. Personally, I prefer signalling an error for invalid values
    4. it propagates (Option -p) the returnlevel ($?) so you may use it for your purpose.
    5. if the process does not react on a normal kill, you may want to add an additional kill -9 a few seconds afterwards.
    1. We can ask timeout to try to stop the program using SIGTERM, and to only send in SIGKILL if SIGTERM didn’t work. To do this, we use the -k (kill after) option. The -k option requires a time value as a parameter.
    1. if you just want to add timeout as an additional option for the entire existing script, you can make it test for the timeout-option, and then make it call it self recursively without that option.
    2. timeout_child () { trap -- "" SIGTERM; child=$!; timeout=$1; ( sleep $timeout; kill $child; ) & wait $child; } And the usage: ( while true; do echo -n .; sleep 0.1; done) & timeout_child 2
    3. You might be confused because echo is both a shell built-in and a separate command.
    1. Couldn't find on Steam. https://steamdb.info/app/793300/ claims that it is there, but https://store.steampowered.com/app/793300/?curator_clanid=4777282&utm_source=SteamDB just redirects to home page.

      Don't redirect to a different URL, esp. without a message explaining why it did so instead of keeping me on the page that I request. That's just incorrect behavior, and a poor UX. Respond with a 404 if the page doesn't exist.!

      That way (among other things), I could use Wayback Machine extension to see if I can find a cached version there.

      But even that (http://web.archive.org/web/*/https://store.steampowered.com/app/793300) is saying "huh?" so I'm confused.

      Where did it go and why?

      I guess it's no longer available, because this page says:

      section_type    ownersonly
      ReleaseState    unavailable
      

      ... but why?

    1. i dont know why everyone wants to **** on everything that is not a "AAA" game, its not in its perfect state, but far from deserve a 3, i will give it a 9 so it counters the "just hate
    1. If any of the inputs are invalid, #execute won't be run.

      It does staged/pipelined execution/validation.

      If any of these stages has any errors, then no other stages will be executed:

      1. validations on the inputs of the interaction itself
      2. run execute, which may:
      3. may use compose, which will (IIUC) abort the entire execute/run early if any of them fail, even if there are later composed interactions still to be run
      4. may try to save inputs into models, which themselves may have validation errors, which (assuming we use errors.merge), will show up on the interaction.errors (but won't abort the rest of the execute)
    2. Grouped inputs It can be convenient to apply the same options to a bunch of inputs. One common use case is making many inputs optional. Instead of setting default: nil on each one of them, you can use with_options to reduce duplication.

      This is just a general Ruby/Rails tip, nothing specific to active_interaction (except that it demonstrates that it may be useful sometimes, and gives a specific example of when you might use it).

      Still, in my opinion, this doesn't belong in the docs. Partly because I think repeating the default: nil for every item is an acceptable type of duplication, which would be better, clearer (because it's more explicit), simpler, keeps those details closer to the place where they are relevant (imagine if there were 50 fields within a with_options block).

      I also think think that it creates a very arbitrary logical "grouping" within your code, which may cause you to unintentionally override/trump / miss the chance to use a different, more logical/natural/important/useful logical grouping instead. For example, it might be more natural/important/useful to group the fields by the section/fieldset/model that they belong with, even if your only grouping is a comment:

      # User fields
      string :name
      integer :age
      date :birthday, default: nil
      
      # Food preferences
      array :pizza_toppings
      boolean :wants_cake, default: nil
      

      may be a more useful grouping/organization than:

      # Fields that are required
      string :name
      integer :age
      array :pizza_toppings
      
      # Fields that are optional
      with_options default: nil do
        date :birthday
        boolean :wants_cake
      end
      

      Or it might be better to list them strictly in the same order as they appear in your model that you are trying to match. Why? Because then you (or your code reviewer) can more easily compare the lists between the two places to make sure you haven't missed any fields from the model, and quickly be able to identify which ones are missing (hopefully intentionally missing).

      In other words, their "optionalness" seems to me like a pretty incidental property, not a key property worthy of allowing to dictate the organization/order/grouping of your code.

    3. There are times where it is useful to know whether a value was passed to run or the result of a filter default. In particular, it is useful when nil is an acceptable value.

      Yes! An illustration in ruby:

      main > h = {key_with_nil_value: nil}
      => {:key_with_nil_value=>nil}
      
      main > h[:key_with_nil_value]
      => nil
      
      main > h[:missing_key]  # this would be undefined in JavaScript (a useful distinction) rather than null, but in Ruby it's indistinguishable from the case where a nil value was actually explicitly _supplied_ by the caller/user
      => nil
      
      # so we have to check for "missingness" ("undefinedness"?) differently in Ruby
      
      main > h.key?(:key_with_nil_value)
      => true
      
      main > h.key?(:missing_key)
      => false
      

      This is one unfortunate side effect of Ruby having only nil and no built-in way to distinguish between null and undefined like in JavaScript.

    4. When you run this interaction, two things will happen. First ActiveInteraction will type check your inputs. Then ActiveModel will validate them. If both of those are happy, it will be executed.

      Failed type checks generate run-time errors. So it's up to the develop to fix these, permanently, since the user can't (99% of time) do anything to fix these.

      Failed validations add errors to interaction.errors object. These are for the user to fix.

    5. outcome.valid?

      This would read better if it were aliased as success?:

      if outcome.success?
      
    6. compose(Add, x: x, y: 3)

      How is this better than simply:

      Add.run(x: x, y: 3)
      

      ?

      I guess if we did that we would also have to remember to handle merging errors from that outcome into self...

    7. Other filters will ignore blocks when given to them.

      Would be better to raise an error if block isn't allowed/expected!

    8. Filters

      Might be helpful / more intuitive to think of filters as... inputs/attributes

      Defining the filters defines which inputs are allowed and which type they are required to be.

    9. If you have value objects or you would like to build one object from another, you can use the converter option. It is only called if the value provided is not an instance of the class or one of its subclasses.
    10. account.first_name = first_name if first_name.present? account.last_name = last_name if last_name.present?

      I guess this is needed so we don't reset to nil (erasing value in database) when they haven't even provided a new value as input.

      But surely there's a cleaner way...

    11. presence: true, unless: 'first_name.nil?'

      This is seemingly contradictory at first glance: Why would we require it to be present ... unless it's not present? I think the reason they did it this way is to allow it to be skipped if and only if it is literally nil but to make it add an error if a blank value such as "" (or even " ") is passed.

    12. It requires an account to update, but the other inputs are optional. If they're missing, it'll ignore those attributes. If they're present, it'll update them.
    13. def edit account = find_account! @account = UpdateAccount.new( account: account, first_name: account.first_name, last_name: account.last_name) end
    14. In this simple example, the destroy interaction doesn't do much. It's not clear that you gain anything by putting it in an interaction.
    15. Note that we have to pass a hash to .run. Passing nil is an error.

      That's why they pass

      params.fetch(:account, {})
      

      instead of simply

      params[:account]
      
    16. The value given to the default option will also be found.

      clarification: using find, if needed

    17. Use the desc option to provide human-readable descriptions of filters. You should prefer these to comments because they can be used to generate documentation.
    18. Lambda defaults are evaluated in the context of the interaction, so you can use the values of other inputs in them.
    19. Setting it to a lambda will lazily set the default value for that input.
    20. hash :with_defaults, default: {} do boolean :likes_cookies, default: true end
    21. By default, hashes remove any keys that aren't given as nested filters. To allow all hash keys, set strip: false. In general we don't recommend doing this, but it's sometimes necessary.
    22. Record filters allow you to require an instance of a particular class (or one of its subclasses) or a value that can be used to locate an instance of the object. If the value does not match, it will call find on the class of the record. This is particularly useful when working with ActiveRecord objects.
    23. You can also create an anonymous interface on the fly by passing the methods option.
    24. ActiveInteraction plays nicely with Rails. You can use interactions to handle your business logic instead of models or controllers.
    25. > RecordInteraction.run!(encoding: 'ascii') => #<Encoding:US-ASCII>

      Makes use of the fact that you can do:

      main > Encoding.find('ascii')
      => #<Encoding:US-ASCII>
      

      and that

      If the value does not match, it will call find on the class of the record.

    26. ActiveInteraction type checks your inputs. Often you'll want more than that. For instance, you may want an input to be a string with at least one non-whitespace character. Instead of writing your own validation for that, you can use validations from ActiveModel. These validations aren't provided by ActiveInteraction. They're from ActiveModel. You can also use any custom validations you wrote yourself in your interactions.
    27. recommended by (also my first sighting of it): https://hyp.is/oDsgQHF0Eeu7kEvGAmpHeQ/github.com/rails/rails/pull/19709

    28. Since interactions behave like ActiveModels, we can use ActiveModel validations with them.
    29. If ActiveModel deals with your nouns, then ActiveInteraction handles your verbs.

      It's a good analogy, but I think it's misleading/confusing/unclear/incorrect, because parts of ActiveInteraction are ActiveModel, so I guess ActiveInteraction deals with your nouns too?

    30. The outcome returned by .run can be used in forms as though it were an ActiveModel object.
    31. You can also create a form object by calling .new on the interaction.
    32. ActiveInteraction also supports merging errors. This is useful if you want to delegate validation to some other object. For example, if you have an interaction that updates a record, you might want that record to validate itself. By using the #merge! helper on errors, you can do exactly that.
    33. ActiveInteraction provides detailed errors for easier introspection and testing of errors. Detailed errors improve on regular errors by adding a symbol that represents the type of error that has occurred.
    34. Since we're using an interaction, we don't need strong parameters. The interaction will ignore any inputs that weren't defined by filters. So you can forget about params.require and params.permit because interactions handle that for you.
    35. Inside #execute, we merge errors. This is a convenient way to move errors from one object to another.
    36. Note that it's perfectly fine to add errors during execution. Not all errors have to come from type checking or validation.
    37. Inside the interaction, we could use #find instead of #find_by_id. That way we wouldn't need the #find_account! helper method in the controller because the error would bubble all the way up. However, you should try to avoid raising errors from interactions. If you do, you'll have to deal with raised exceptions as well as the validity of the outcome.

      What they're referring to:

      Account.find('invalid') will raise an error but Account.find_by(id: 'invalid') will not.

    38. Why is all this interaction code better? Two reasons: One, you can reuse the FindAccount interaction in other places, like your API controller or a Resque task. And two, if you want to change how accounts are found, you only have to change one place.

      Pretty weak arguments though...

      1. We could just as easily used a plain object or module to extract this for easy reuse and having it in only one place (avoiding duplication).
    39. This probably looks a little different than you're used to. Rails commonly handles this with a before_filter that sets the @account instance variable.
    40. For this one we'll define a helper method to handle raising the correct errors. We have to do this because calling .run! would raise an ActiveInteraction::InvalidInteractionError instead of an ActiveRecord::RecordNotFound. That means Rails would render a 500 instead of a 404.

      True, but why couldn't it handle this for us?

    41. value returned from #execute

      Why not follow Ruby Proc convention of calling it call?

      execute seems like a synonym for call, so given these 2 equivalent options, it seems better to prefer the one more idiomatic in Ruby.

    42. By convention, we call this an outcome
    43. Call .run on your interaction to execute it.

      Why not follow Ruby Proc convention of calling it call?

      run seems like a synonym for call, so given these 2 equivalent options, it seems better to prefer the one more idiomatic in Ruby.

    44. It's an implementation of the command pattern in Ruby.

    Tags

    Annotators

    URL

    1. The problem is that you what you want is actually not de-structuring at all. You’re trying to go from 'arg1', { hash2: 'bar', hash3: 'baz' }, { hash1: 'foo' } (remember that 'arg1', foo: 'bar' is just shorthand for 'arg1', { foo: 'bar' }) to 'arg1', { hash1: 'foo', hash2: 'bar', hash3: 'baz' } which is, by definition, merging (note how the surrounding structure—the hash—is still there). Whereas de-structuring goes from 'arg1', [1, 2, 3] to 'arg1', 1, 2, 3
    1. {a: 1, b: 2, c: 3, d: 4} => {a:, b:, **rest} # a == 1, b == 2, rest == {:c=>3, :d=>4}

      equivalent in javascript:

      {a, b, ...rest} = {a: 1, b: 2, c: 3, d: 4}
      

      Not a bad replacement for that! I still find javascript's syntax a little more easily readable and natural, but given that we can't use the same syntax (probably because it would be incompatible with existing syntax rules that we can't break for compatibility reasons, unfortunately), this is a pretty good compromise/solution that they've come up with.

    2. You can rescue at the method level, but more likely you’d want to rescue at the statement level.
    3. In Ruby 3 we now have a “rightward assignment” operator. This flips the script and lets you write an expression before assigning it to a variable. So instead of x = :y, you can write :y => x
    4. (Yay for the hashrocket resurgence!)
    5. we’re going to look how improved pattern matching and rightward assignment make it possible to “destructure” hashes and arrays in Ruby 3—much like how you’d accomplish it in, say, JavaScript
  2. www.metacritic.com www.metacritic.com
    1. Please, do not buy this. I am really tired of "games" that are given critical praise because its cool to praise or because its political correct to do. I will break up my review in points so its clear why I dislike this "game" : 1) This is not a game. This is a short story, like an interactive book. 2) This game is so short, that I completed it in a 3 hour bus ride. It was boring. 3) Its a story of a girl that have to take the reigns of her life after divorce. WOMAN EMPOWERMENT. Now you know why this game is rated so highly 4) This is a MOBILE GAME. I paid $3 to play on an iphone (after watching a gaming channel give it GOTY contender. Needless to say, I never watched that gaming channel again). I FELT I WAS ROBBED OF TIME AND $3. Imagine how much I hated this game to feel like I was robbed even though it costed me only $3. 5) This game costs $7 on the eshop. You could buy CELESTE for $9 on sale on the Eshop. That is a great game. I recently bought Hollow Knight for $7 on Playstation. This interactive novel should not be sold as a game. Period. It is a waste of time and money.

      Nothing wrong with interactive novels being sold in the same store as games... as long as it's clear what it is (no false advertising).

      Somewhat agree with some of the other points...

    1. That’s it, plain and simple. But if you want the legalese version, dive into it here.
    2. What we do collect:The translated words you encounter so that we know what words you are exposed to and can serve up appropriate vocabulary quizzes.Any vocabulary quizzes you see and the results of those quizzes so that we can keep track of how well you know each vocabulary concept.Anonymized (not linked to anyone's particular account) web page URLs, whether translations show up on them, and whether any bugs or errors occur on those pages so that we can better detect any broad issues affecting our user base.
  3. www.joinhoney.com www.joinhoney.com
    1. Honey does not track your search engine history, emails, or your browsing on any site that is not a retail website (a site where you can shop and make a purchase). When you are on a pre-approved retail site, to help you save money, Honey will collect information about that site that lets us know which coupons and promos to find for you. We may also collect information about pricing and availability of items, which we can share with the rest of the Honey community.
    1. For example, a real estate agentCommercial Real Estate BrokerA commercial real estate broker is a middleman between sellers and buyers of commercial real estate, who helps clients sell, lease, or purchase commercial real estate. A commercial real estate broker has the freedom to work either as an independent agent, or as a member of a commercial real estate brokerage firm. with an established network of colleagues for contacting potential home buyers, in addition to a broad range of market information and advertising outlets. Wholesalers include the middlemen between manufacturers, producers, and retailers. The retailers themselves are the middlemen between wholesalers and the end customers.
    1. Instead of modifying /usr/share/applications/google-chrome.desktop, the file can be copied into ~/.local/share/applications/google-chrome.desktop and modified without root access. This file will take precedence over the global desktop file.
    2. This solution also works for chromium-browser.
    1. Nevermind, I use now reform-rails
    2. @adisos if reform-rails will not match, I suggest to use: https://github.com/orgsync/active_interaction I've switched to it after reform-rails as it was not fully detached from the activerecord, code is a bit hacky and complex to modify, and in overall reform not so flexible as active_interaction. It has multiple params as well: https://github.com/orgsync/active_interaction/blob/master/spec/active_interaction/modules/input_processor_spec.rb#L41

      I'm not sure what he meant by:

      fully detached from the activerecord I didn't think it was tied to ActiveRecord.

      But I definitely agree with:

      code is a bit hacky and complex to modify

    3. you mean Action Form, right?
    1. (To clarify, I'm not personally needing / waiting on this change (not currently anyway). I was just looking at all the open issues in this project while deciding whether I should start using ActiveIntegration in my project...)
    2. Now that v4 is released, maybe we can look again into merging this?
    3. Any idea @AaronLasseigne if this is mergeable?
    4. This is a breaking change so it'll have to go into a major release. I was working on a v4 release but it's too much. I think I'm going to pair it back and we can add this to the new v4. When I have that ready, I'll rebase the merge onto that branch.
    5. pair

      pare

    1. For now I've worked around this by putting all the key-value pairs into an array before passing them into the interaction, then re-building the hash inside the interaction. It works, but it requires some extra code
    2. You can use it by allowing a hash with arbitrary keys, but that loses type-safety one that object.
    3. No one has requested it before so it's certainly not something we're planning to add.
    4. I'm sure there will be a few other people out there who eventually want something like this, since Interactions are actually a great fit for enforcing consistency in data structures when working with a schemaless NoSQL store, but obviously it's still a bit of a niche audience.
    5. To give a little more context, structures like this often come up in my work when dealing with NoSQL datastores, especially ones that rely heavily on JSON, like Firebase, where a records unique ID isn't part of the record itself, just a key that points to it. I think most Ruby/Rails projects tend towards use cases where these sort of datastores aren't appropriate/necessary, so it makes sense that this wouldn't come up as quickly as other structures.
    6. Thanks, I'll continue leaning on the array workaround for my use case then.
    1. I had to use something like this: occupancy.errors.messages.each do |column, messages| messages.each { |m| errors.add(column, m) } end
    2. I have a Post object that has_one :schedule with accepts_nested_attributes_for :schedule as well. The latter method sets autosave: true, which unfortunately has the effect of hoisting up errors into the parent object so that the errors object on Post looks like this: (byebug) post.errors.details {:"schedule.publish_at"=>[{:error=>:blank}]}
    3. The naughty pseudo-attribute name with the dot in it
    4. The Rails side doesn't support any handling of these nested attribute names in the error yet it generates them from somewhere.
    1. I bought this software mainly for the multiple camera capture. I upgraded to the Pinnacle Studio 24 Ultimate.The Ultimate version still restricts how many cameras can be added.To add more cameras requires purchasing another upgrade.Their 'Ultimate' version isn't the ultimate if they are still holding back features.
    2. There is an evil genius lurking around in this software, playing withyour emotions and your work. This monster wants to sell its product by any means,even if it means shutting down your work at a crucial moment so that you would run to buy the next version. Update this and update that and buy! buy! buy!For your own wellbeing, don't buy it.
    1. Learn more about how we made the decision to put our guidance in the public domain
    2. and let us know how you are putting Hypothesis Help to good use
    3. In order to support easy reuse, revision, remixing, and redistribution, the entire Hypothesis Help knowledge base by Hypothesis is dedicated to the public domain via CC CC0 1.0. While we appreciate attribution and links back to Hypothesis from anywhere these works are published, they are not required.
    1. I don't think seeing it in Rails PRs naturally means we should do it blankly. Put it another way, what's the justification in those PRs for doing it?
    2. The rationale is that it's actually clearer to eager initialize. You don't need to worry about timing/concurrency that way. Lazy init is inherently more complex than eager init, so there should be a reason to choose lazy over eager rather than the other way around.
    3. I like the clarity of this approach instead of stuffing it in initialize.
    4. collect_errors_from(model) vs. collect_errors_from(form) where form is one of the sub forms of the form (yes, I don't like that either).

      Why don't you like it? Looks reasonable to me...

    5. The main realization came when I figured out that the main_model was just another association. This means we can move a lot of logic to just that class and reason about it a lot better.
    1. But ActiveModel doesn't support out of the box argument parsing, e.g. having a datetime attribute be a datetime attribute and a boolean attribute be a boolean attribute.

      Doesn't it now, with the (newer) ActiveModel::Attributes API?

    2. class FormsController < ApplicationController class SearchForm < ActiveModel::Form

      I kind of like how they put the form class nested directly inside the controller, although I would probably put it in its own file myself, unless it was quite trivial.

    3. support round-tripping (assigning the submitted params again)
    4. ActiveModel::Form happened because the "tableless model" presented in RailsCast 219 wasn't as powerful as the "real deal" from RailsCast 193.
    1. The great thing about working with reinteractive is you get to work directly with the developers, which is a huge plus. As a technical founder, I find proxying through a project manager adds unnecessary layers of complexity and creates opportunity for human error.
    2. Download this free e-book to learn how.
    3. You provide the vision, we'll handle the rocket science!
    1. So how are we going to create a model that doesn’t have a database table behind it? There are several potential solutions including various plugins but we’re going to use the method described in an entry on the Code Tunes blog. This shows a techinque that involves overriding a couple of methods in an ActiveRecord model and then manually defining the columns in the model file rather than in the database table. In our Recommendation model we’ll add in the two overridden methods and then use the column class method to define the columns in a similar way to how they’re defined in a migration file.

      Does this still work in Rails 6? I wonder.

    2. We could quite easily create a model class that isn’t based on ActiveRecord and have it work as Rails is quite decoupled from ActiveRecord, but there are advantages to keeping our model class inheriting from ActiveRecord.
    1. Examples of different ways of defining forms

      Wow, that's a lot of different ways.

      The inline_form way in particular seems interesting to me, though it's worth noting that that method is just an example, not actually part of this project's code, so it's not really a first-class option like the other options.

    2. Bureaucrat doesn't define save

      It's probably just as well, since it will almost always need to be overridden with custom logic...

    1. Scrivener is Bureaucrat's little brother. It draws all the inspiration from it and its features are a subset of Bureaucrat's.
    2. The assert method is used by all the other assertions. It pushes the second parameter to the list of errors if the first parameter evaluates to false or nil.

      Seems like these helper functions could be just as easily used in ActiveRecord models. Therefore, they should be in a separate gem, or at least module, that can be used in both these objects and ActiveRecord objects.

    3. Read about the motivation to understand why this separation of concerns is important.
    1. or use Github's discontinued Rubygems server
    2. Unfortunately the widespread adoption of this practice led to a huge number of orphaned gems that usually have only a single or at most a handful of releases. Additionally these forked gems often retained their upstream github source code url, so on the Ruby Toolbox these forks receive a high popularity ranking.
    1. As a result, dry-types, dry-struct and dry-schema were born. These projects should be considered as virtus' successors, with better separation of concerns and better features.
    1. I think a better, more immediately understandable name for this concept would be command object, because it lets you pass around commands (or a list of commands) as objects.

      That's the only thing you really need to know abut this pattern. The rest seems like boring implementation details that aren't that important, and that naturally follow from the primary definition above.

    2. Uses
    3. A sample UML class and sequence diagram for the Command design pattern.
    4. The central ideas of this design pattern closely mirror the semantics of first-class functions and higher-order functions in functional programming languages. Specifically, the invoker object is a higher-order function of which the command object is a first-class argument.
    1. For the usage in society, see Second-class citizen.
      1. Ironic that this reference is ostensibly about the usage of "first-class citizen" in society, yet it links to a seemingly-mismatched (by name only, that is) article, entitled "second-class citizen".

      2. Ironic that the first-class (unqualified) article is about the figurative meaning of "citizen" used in computer science, and that the page describing first-class and second-class status of the more literal citizens in society is relegated to what I kind of think is a second-class position in the encyclopedia (because it takes the #2 position numerically, even though it is (at least as is implied in this reference) also about first-class citizens (though the word "first-class" does not appear a single time in that article, so maybe this reference is the one that is more ironic/incorrect).

    2. In programming language design, a first-class citizen (also type, object, entity, or value) in a given programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, modified, and assigned to a variable.
    1. In computer science, a programming language is said to have first-class functions if it treats functions as first-class citizens.
    1. describe '.validate(context, filters, inputs)' do let(:inputs) { {} } let(:filter) { ActiveInteraction::Filter.new(:name, {}) } let(:interaction) do
    1. rafaelfranca closed this on Feb 27, 2018
    2. We are still open to the idea but the implementation should leverage the attributes API introduced in Rails 5.2 in Active Model.
    3. Is there are any possibility to speedup this pull-request to be merged?
    4. Fork rails, add github.com/georgebrock/rails as a remote, merge this branch into rails/4.0.2 (the tag), and then use your fork of Rails: gem 'rails', github: 'yourusername/rails'
    5. Sorry for the delay, life got in the way. I should have some time to pick this up again next week.
    6. I like this idea a lot. I have had problems too with having multi-parameters assignments depending so heavily on active record.
    7. If you take it to it's logical conclusion you'd only accept the correct types for boolean, integer, decimal, etc. columns, which is obviously crazy.