RSS
 

Ruby RSpec FactoryBot traits and transient via ChatGPT

15 Dec

The following was edited together from a series of questions to ChatGPT on the topic. Currently, I cannot identify sources of the originating content. My role was to edit ChatGPT into the following.

FactoryBot

RSpec is a testing framework for the Ruby programming language, and FactoryBot (formerly known as Factory Girl) is a library for creating test data in Ruby. Together, these tools can be used to write unit-tests for a Ruby application.

In FactoryBot, a factory is a blueprint for creating test data objects. A factory can define various attributes of the objects it creates, such as the object’s type, the values of its attributes, and any associations it has with other objects.

Traits

A trait in FactoryBot is a named group of attributes that can be can be applied to a factory, used to create an object. Traits allow you to define common attribute sets that can be shared across multiple factories or used to override the default values in a factory. Instead of having to specify the same attributes every time you create an instance of a factory, you can use a trait to define those attributes once, and then include the trait in any factory that needs those attributes.

If you have a factory for creating a user object in your application, this factory might have various attributes for the user, such as their name, email address, and password. You can use a trait to group together a set of attributes that are commonly used together.

Here’s an example of how you might use a trait in your factory:

FactoryBot.define do
  factory :user do
    name 'John Doe'
    email 'johndoe@example.com'
    password 'password'

    trait :admin do
      admin true
    end
  end
end

In this example, the :admin trait sets the admin attribute to true for the user object. You can use this trait when creating a user object to specify that the user should be an admin. Here’s an example:

user = FactoryBot.create(:user, :admin)

This will create a new user object with the name, email, password, and admin attributes set. The admin attribute will be true because of the :admin trait.

Here’s an example of how you might use a trait to define a :with_email attribute for a User factory:

# Define the trait
RSpec.define_trait :with_email do
  transient do
    email { "user@example.com" }
  end

  after(:build) do |user, evaluator|
    user.email = evaluator.email
  end
end

# Use the trait in a factory
FactoryBot.define do
  factory :user, traits: [:with_email] do
    # other attributes for the user go here
  end
end

# Create an instance of the factory with the trait
user = create(:user, :with_email)

In this example, the :with_email trait defines an attribute email with a default value of "user@example.com", and an after(:build) hook that sets the user’s email attribute to the value of the email attribute when the factory is built. When you create an instance of the :user factory and include the :with_email trait, the user’s email attribute will be set to the value defined in the trait.

Overall, traits in FactoryBot provide a way to group together commonly used sets of attributes, which can make it easier to create objects in your tests.

Transients

A “transient attribute” is an attribute that is not saved to the database when an object is created. This can be useful when you want to specify certain values for an object when it is created for a test, but you don’t want those values to be persisted in the actual database. …are used only for the duration of a factory’s execution. They can be useful for setting temporary values that are needed for a specific test but are not relevant for the long-term state of the object.

To use a transient attribute in a factory, you can define it using the transient method’s block, in a FactoryBot factory. For example, you might define a :admin trait for a User factory that sets the admin attribute to true and the email attribute to a specific value.

FactoryBot.define do
  factory :user do
    transient do
      admin false
    end

    name 'John Smith'
    email 'john@example.com'
    password 'password'
    is_admin admin
  end
end

In this example, the admin attribute is a transient attribute that is set to false by default. When an instance of the :user factory is created, the is_admin attribute will be set to the value of the admin transient attribute.

Its value can be set using the after(:build) hook, as in:

FactoryBot.define do
  factory :user do
    transient do
      admin false
    end

    after(:build) do |user, evaluator|
      user.admin = evaluator.admin
    end
  end
end

You can then use the transient attribute when creating an object using the factory:

user = FactoryBot.create(:user, admin: true)

This will create a User object with the admin attribute set to true.

after(:build)

after(:build) is a hook that allows you to specify a block of code to be run after an object is built using a factory. The :build symbol refers to the  build method provided by FactoryBot, used to create an instance of a model without saving it to the database. The block passed to after(:build) is executed after the object is built, but before it is returned. This allows you to modify the object or perform other actions on it before it is used in your tests.

Here’s an example to customize the behavior of a factory:

# Define a factory for a User model
FactoryBot.define do
  factory :user do
    # Set some attributes for the user
    name { "John Smith" }
    email { "john@example.com" }
    password { 'password' }

    # Use the after(:build) hook to customize the user
    after(:build) do |user|
      user.name = 'Jane Smith' if user.email == 'jane@example.com'
    end
  end
end

# Now, when you use the factory to build a new user, it will have the
# attributes specified in the factory as well as the password set to "password"
user = build(:user)

The block takes a single parameter, which is the object that has been built by the factory. In this example, the after(:build) block modifies the name attribute of the user object if the email attribute is set to 'jane@example.com'.

sets the password attribute of the user object, being created by the factory, to the value “password”.

You can also pass a symbol representing a method to after(:build) instead of a block, like this:

after(:build, &:set_password)

This will call the set_password method on the object after it has been built by the factory.

You can also define multiple after(:build) blocks in a single factory; each block will be executed in the defined order:

factory :user do
  # define user attributes here

  after(:build) do |user|
    user.password = "password"
  end

  after(:build) do |user|
    user.email = "user@example.com"
  end
end

# create a new user object with the password attribute set to "password" and the email attribute set to "user@example.com"
user = build(:user)

Note that the after(:build) is only run when you use the build method to create an instance of the model. It will not be run when you use the create method, which both builds and saves the model to the database. If you want to customize the behavior of a factory when it is used with create, you can use the after(:create) hook instead.

 
 

Frontend Security Recipe Checklist

03 Jan

Even as the number of frontend programming vulnerabilities grows continually, many are not difficult to combat; you simply need to remember to fortify your frontend security against them.

 
 

Catching the Technology Train, After I’d Disembarked

12 Jun

https://www.capitolcorridor.org/wp-content/uploads/2016/04/Capitol_Corridor_SanJoaquin.jpg

Staying away from programming for too long, things change faster than I’d ever expected. Even with a strong foundation, when things move ahead so quickly, too many things change and it isn’t as easy to hop back on the train, as I would have thought. Today, I am trying to catch up with technology train that is web development. How did I become so disconnected?

  1. My initial disinterest was that I wasn’t very interested. With web “development,” writing text-markup was not “programming” (it still isn’t). It has taken a couple of decades for web-programming to require the skills of true developers. But it is here, today. In the mean time, I’d left it behind and as a result, it left me behind.
  2. When I recently started looking at getting into web-development, the landscape was changing and evolving so quickly that it was hard to pin down which of the dozens of technologies to focus on. If I’d picked Perl, ColdFusion, Ruby, AngularJS, etc.… ”the list is endless” I’d be an expert in another obsolete technology. However, avoiding a pick, meant that I did not get my hands dirty and did not stay keen about the evolving landscape of web-development.
  3. What I never expected is that it isn’t just the languages and frameworks which have changed, it is also the technology infrastructure which has changed and, notably, this has changed development workflow.

The result is that, not only do I need to learn new languages and their nuances, I even need to learn a new workflow, a new way of doing programming. While I am not starting from scratch, a lot of my prior “expertise” is not directly applicable; so it feels like starting from scratch.

I could just stick to the old technologies that I am still expert at, but that isn’t cutting edge. Still I could do that. Then I wouldn’t have anything to be stressed about. And, that wouldn’t be so bad, now would it?

 
 

ReactJS: componentWillReceiveProps() is Dead! (*sniff*)

21 Apr

ReactJSThings evolve. ReactJS evolves. With version 16.3, there were several changes to the component life-cycle methods. In particular, componentWillReceiveProps is disappearing. In its place, they say, you can use the getDerivedStateFromProps static function. I found this a bit challenging, but I did find an interesting pattern when the component-state was dependent on fetched information.

I should mention that I had a specific goal to better encapsulate data within the component. While I could pass in all the needed data as properties, that would require the surrounding component know what to pass and how to get it. That shouldn’t necessarily be necessary; the component knows what it needs and how to retrieve it.

For example, say you have a component which accepts a phone number and displays the phone number and the state that it’s from. Certainly, you could write a simple component that accepts both pieces of information as properties.

<ShowPhoneLocation number="+12065551212" city="Seattle" />

Which might be implemented as:

class ShowPhoneLocation extends React.Component {
  render() {
    return (
      <div>{this.props.number} is from {this.props.city}</div>
    )
  } // render()
} // class ShowPhoneLocation

But, since the component should be able to infer the state from the phone number (by its area code), it shouldn’t be incumbent on its container to know what it is.

class ShowPhoneLocation extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    let location = getCityFromPhone(nextProps.number)
    return {
      city: location
    }
  }
  render() {
    return (
      <div>{this.props.number} is from {this.state.city}</div>
    )
  } // render()
} // class ShowPhoneLocation

That’s all well and good, but what if getCityFromPhone() has to call a web service? We don’t want getDerivedStateFromProps() to stall, waiting for a response. However, it is static and does not have a this reference to the object for which it is returning state; so an asynchronous fetch doesn’t know what object’s state to set. Instead, don’t wait for the result to save in the state, save the request’s Promise in the state and update the state, once the promise resolves.

function getCityFromPhone(number) {
  return fetch('http://saas.com/get/'+number+'/city') // Returns fetch promise
}
class ShowPhoneLocation extends React.Component {
  static getDerivedStateFromProps(nextProps, prevState) {
    let location = getCityFromPhone(nextProps.number)
    return {
      city: location
    }
  }
  componentDidUpdate() {
    let location = this.state.city
    if (location instanceof Promise) {
      this.setState({ city: '...waiting...' })
      location.then(city => this.setState({ city: city }) )
        .catch(() => this.setState({ city: 'not found' }) )
    }
  }
  render() {
    return (
      <div>
        {this.props.number} is from {this.state.city instanceof Promise
         ? '...'
        : this.state.city}</div>
    )
  } // render()
} // class ShowPhoneLocation

In componentDidUpdate() you can define the completion handlers to set the object’s state, base on the returned information from the service.

It is a common pattern to perform a fetch in componentDidMount(). The problem is that there may not be enough information to perform the fetch, that early, or the information for the fetch changes after the component has been mounted.

I am going to miss componentWillReceiveProps()… without it, things become a bit more convoluted but it’s going the way of the Dodo.

 

Your Elevator Pitch is Important for YOU

20 Oct

It was StartupWeek 2017 in Seattle, recently. It was a time when anyone with a startup or an idea to start a business was roaming the city’s talks, gatherings, and events to learn how to become a success. Networking and chatting was a big part of the activity, so I got to hear a lot of people try to describe their ideas. I noticed that many of those early in their startup are not very clear about what they are trying to do or they take 20-minutes before they are… they have no elevator pitch.

What is an Elevator Pitch?

Can you encapsulate the essence of your startup idea so that you can express it in the time it takes to travel a few floors of an elevator? If you were to meet the person that could most help you with your startup, as you enter an elevator, can you clearly articulate and spark their interest before either of you exit the elevator?

An elevator pitch encapsulates a description of your startup, its meaning and purpose, in as few words as possible.

Why is An Elevator Pitch Important?

At every stage of the evolution of a startup, you will need help. Whether looking for employees, co-founders, investors, advisors, or customers, you will need to pique their interest quickly. You’ll want them to say, “I want to hear more!” You want them to invite you to follow them off the elevator.

In an elevator, you have a captive audience; but you will only hold their attention for so long. Of course this even more true outside an elevator where it is more difficult to hold their attention. So, it is important to keep your pitch succinct.

Why Else is an Elevator Pitch Important?

Okay, if you are already familiar with what an elevator pitch is, then I haven’t told you anything new. The real reason why it is important for you to create an elevator pitch is to help you crystallize your startup idea. The process of building and refining a pitch forces you to think very carefully about your idea. It forces you to narrow in on the essence of your idea… to identify the most salient elements of your idea. In that process, it might even help you set priorities for your startup.

Get into the habit of iterating your elevator pitch. As your startup lives, it evolves. It’s goals may change. A pitch should correspond to the changes that are occurring to the company. Regular updating of the elevator pitch might highlight changes that you did not anticipate and allow you to encourage or halt changes, as you see fit. It will certainly ensure that your message matches what you are building.

What Does an Elevator Pitch Look Like?

There are a lot of books, blogs, and advice (like my prior post) about what should be covered in a startup elevator pitch. At a minimum, you should identify what the problem is that you are trying to solve and how you are solving it.

How long should an elevator pitch be? Simply, as short as possible. Elevator rides can vary… you will have varying amounts of time to present your message. Start with a 3-minute pitch. Then work on shortening it to 2-minutes… 90-seconds… 60-seconds… 30-seconds! Ideally, you would be able to describe your company in a sentence or two.

Cutting words is not easy, but this exercise of paring down your message forces you to evaluate your company’s purpose. It is important to present a focused, achievable idea in the pitch message. If the idea is being lost as words are cut, then perhaps the company’s goals need to be simplified or scaled back. Or, you need to prioritize goals so that a message can focus on a narrower set of primary objectives.

Should you interest someone enough for them to want to hear more, be prepared to present longer descriptions. As the talks get longer, they begin to sound more like your full-fledged presentations. But, be prepared to work within any time-constraint you might be faced with. You can build out to 5-, 10-, 20-minute presentations. With longer pitches and presentations, you should create different versions targeted at different audiences, as necessary.

Eventually, you will have a range of pitches from a couple of sentences to a full-presentation at your fingertips… and on the tip of your tongue.

An Elevator Pitch Informs Others and Yourself

It is important to get your message across, quickly, as you meet people who might be helpful to your startup. Just as important, creating an elevator pitch will force you to identify and prioritize the “minimum viable product” of your idea.

  1. Research the elements of what goes into a startup elevator pitch
  2. Isolate the essence of your startup
  3. Articulate your startup in 3-minutes (or less)
  4. Further net out essential elements of your startup and your message for shorter versions of your pitch
  5. Longer presentation-pitches can fill the gaps between your elevator pitch and a full presentation.

Having a concise pitch means you had to identify the focus of your company. Continually adjusting your pitch to match your evolving startup keeps you in-tune with your venture. This, in itself, will improve your understanding of your company and allow you to sharpen its focus.

 
No Comments

Posted in Startup

 

HTTP via Telnet

02 May

Okay, back to basics, the very low level basics. HTTP is text based, telnet enables a network connection via a text-based command line. All good. We can use telnet to talk to a web server by manually typing text to it, if you know the details of the content syntax to send HTTP via telnet.

Though this is not done, often, it is still good to know how it can be done. In fact, since these basics rarely change, I shouldn’t have even had to write this down, since it should be innate.

Sending HTTP Using Telnet

Once you get telnet running (see section, below), it is just a matter of typing HTTP to the server, manually.

There are four pieces the first three are shown, here:

GET / HTTP/1.1
Host: cachecrew.com
Connection: close
  1. This is the start of the HTTP commands you can enter. The first line must specify the HTTP method. There are three parts: Read the rest of this entry »
 
 

Promises, Promises… Timeout!

25 Apr

I was playing with ES6’s new Promises, for the first time, this week. Then, I was looking at the ugliness of using a browser’s setTimeout() function and thought that it would look better as a Promise.

tl;dr summary: A Simple Promise Version of “setTimeout()”

If we do it right, you simply specify the timeout period and implement a handler for then() to invoke:

timeout(5000) // Delay for 5000 ms
   .then(function () {
      // Do, here, whatever should happen when the time has elapsed…
   });

Or, since this is ES6, we might as well use arrow-function shorthand:

timeout(5000).then( () => {
   // do your thing, here…
})

Implementation

The setTimeout() already functions a bit like a Promise, without matching the promise-pattern and syntax, so converting it to a Promise is pretty easy: Read the rest of this entry »

 
 

Reviving the ccPhp Framework

10 Nov

I had kinda given up on my PHP framework (as I’d mentioned in my “Simplicity via PHP Frameworks” article). But as I embarked on another little web project and realized that I might b … Reviving ccPhp. It took longer than I would have liked, to get up and running. … I noted that, at its core, it has a very programmatic approach to building a web page. That is, it assumes …

[This post was hacked, due to a WordPress bug, and I hadn’t backed it up. I tried to find it via some of the web caching/archival sites like achive.org, but, to no avail. The snippet above was a snippet from what the Facebook page preserved. A lot of thought went into the post, but once I spew my thoughts out onto the page, I wipe my brain of the details. If I find the rest, I’ll update this.]

 
 

Simplicity via PHP Frameworks

05 Apr

PHP language and web-technologyA long time ago, I’d endeavored to create my own lightweight PHP framework, ccPHP. It was a good exercise, but never reached prime time. Around that time I began to notice others endeavoring to do the same thing (i.e., create simpler, lighter weight PHP frameworks that didn’t take more time to learn than to implement the project). I’ve been away for a while and things have changed.

  1. The continued refinement and simplification of frameworks.
  2. The greater emphasis on frontend apps to do more of the work that used to be done in the middle tier.
  3. The ubiquity of RESTful interfaces, the dividing line between front-ends and servers.

Micro-PHP Frameworks

I doubt that I will ever finish my own framework, now that others are a lot closer to the goals that I was moving towards. And, right now, I simply want to find a lightweight modular frameworks that truly help me get my core work done. Dragan Gaic did a great survey of the PHP hot frameworks in Top 12 Best PHP RESTful Micro Frameworks (Pro/Con).

A key feature of such frameworks is for them to be modular to allow me to pick and choose only the components I need, rather than have to install, understand, and run a bunch of functionality that I do not need. It makes it harder for the developer and impacts performance of the results. Model-View-Controler (MVC) is a common software architecture pattern. With the client side being far more capable of managing the view part, on its own, the server side can be simpler. Instead of cluttering up the server-side app with trying to display information, it can simply focus on securing data and access and providing data services via RESTful interfaces.

So, what I am looking for are pieces to help me access persistent data and build RESTful interfaces. And something to help keep all the code flow organized. Based on the article, I can look at Silex, Slim, Lumen, or Phalcon for the latter. For database access, Ive worked with RedBeans before and liked it, so I will probably pick that up again. If one of the frameworks doesnt help implement and configure a RESTful interface simply, then I may get back into the framework building business again.

Model: RedBeans
View: Frontend client
Controler: one of Silex, Slim, Lumen, or Phalcon

A WordPress bug allowed my website to be hacked. I thought this was lost forever until I thought to reconstitute it from http://Archive.org!!

 

Solving git Problems with Prune

28 Jan

gitThe more I use git, the more I find that it is not as bullet-proof as I have been led to believe. Though, so far, there seems to always be a way out of a problem. Such is the case when I was unable to update a local branch from our

[code light=”true”]
Your configuration specifies to merge with the ref ‘my_branch’
from the remote, but no such ref was fetched.
[/code]

No matter what I did to recreate my local branch, I could not pull from the remote. Google and StackOverflow was of no help—misdirecting to unhelpful information. It turned out that even through I’d fetched the current state of the remote server, my index was still showing a remote branch that did not really exist. Running the following command cleaned that up—and all was well:

[bash light=”true”]
$ git remote prune origin
Pruning origin
URL: git@github.….com:….git
* [pruned] origin/my_branch
$ _
[/bash]

For some reason there was a phantom remote branch that fetch did not update in my local index, properly. Otherwise prune is pretty innocuous, so it might be worth running, every once-in-a-while to make sure that your index is an accurate reflection of the remote.

Enhanced by Zemanta