Categories
discuss

How to forEach in Elixir

How do you forEach in Elixir? In JavaScript (and most languages have an equivalent), I can iterate through the various items in a list and do something with side effects like outputting to the console.

[1,2,3].forEach(function(num) {
    console.log(num);
});

//=> 1
//=> 2
//=> 3

Is there an equivalent in elixir?

Answer

Iterating through a collection is most often handled with the Enum module. Enum.each/2 is what you’re looking for if you want to generate side effects.

Enum.each/2 function takes two arguments: your collection and a function to run on every member of the collection.

Like so:

iex(3)> Enum.each([1, 2, 3], fn x -> IO.puts x end)
1
2
3
:ok

I wrote a blog post about this recently which goes into more details. The post is a comparison between Elixir and Ruby, but the same exact logic applies to JavaScript.

Categories
discuss

Google Visualization: Animated Line Graph –incremental rather than all at once?

Right now my code looks like this:

function drawChart() {

     var data = new google.visualization.DataTable();
      data.addColumn('string', 'Year');
      data.addColumn('number', 'Revenue');

      data.addRows([
        ['', 0],
        ['2008', 123],
        ['2010', 213],
        ['2012', 654]
      ]);

    var options = {
      hAxis: {textStyle:{color: '#FFF'}},  
      vAxis: { baseline:0, baselineColor: '#FFF', gridlineColor: '#FFF',  textStyle:{color: '#FFF'} },
      backgroundColor: 'transparent',
      legend: { position: 'none' },
      colors: ['#FFF'],
      textStyle:{color: '#FFF'},
      pointSize: 10,
      series: {
            0: { pointShape: 'star'}
        },
      animation: {startup: true, duration: 5000, easing: 'linear',}

    };



    var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));

chart.draw(data, options);
  }

What I want is for my animation to incrementally reveal each row. How do I go about doing this?

Any help would be greatly appreciated.

Answer

the chart must be drawn for animation to occur

hold on to the data and only draw one row at a time

see following working snippet…

google.charts.load('current', {
  callback: function () {
    var rawData = [
      [0, 0],
      [1, 2],
      [2, 1],
      [3, 4],
      [4, 2],
      [5, 8],
      [6, 3],
      [7, 16],
      [8, 4],
      [9, 32]
    ];

    var data = new google.visualization.DataTable({
      "cols": [
        {"id":"","label":"X","type":"number"},
        {"id":"","label":"Y","type":"number"}
      ]
    });

    var options = {
      pointSize: 4,
      animation:{
        startup: true,
        duration: 600,
        easing: 'in'
      },
      legend: 'none',
      hAxis: {
        viewWindow: {
          min: 0,
          max: 9
        }
      },
      vAxis: {
        viewWindow: {
          min: 0,
          max: 32
        }
      }
    };

    var chart = new google.visualization.LineChart(document.getElementById('chart_div'));

    drawChart();
    setInterval(drawChart, 1200);

    var rowIndex = 0;
    function drawChart() {
      if (rowIndex < rawData.length) {
        data.addRow(rawData[rowIndex++]);
        chart.draw(data, options);
      }
    }
  },
  packages:['corechart']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

EDIT

for smoother action, wait for the chart’s 'ready' event before drawing again.

see following working snippet…

google.charts.load('current', {
  packages:['corechart']
}).then(function () {
  var rawData = [
    [0, 0],
    [1, 2],
    [2, 1],
    [3, 4],
    [4, 2],
    [5, 8],
    [6, 3],
    [7, 16],
    [8, 4],
    [9, 32]
  ];

  var data = new google.visualization.DataTable({
    "cols": [
      {"id":"","label":"X","type":"number"},
      {"id":"","label":"Y","type":"number"}
    ]
  });

  var options = {
    pointSize: 4,
    animation:{
      startup: true,
      duration: 600,
      easing: 'in'
    },
    legend: 'none',
    hAxis: {
      viewWindow: {
        min: 0,
        max: 9
      }
    },
    vAxis: {
      viewWindow: {
        min: 0,
        max: 32
      }
    }
  };

  var chart = new google.visualization.LineChart(document.getElementById('chart_div'));

  google.visualization.events.addListener(chart, 'ready', function () {
    drawChart();
  });

  var rowIndex = 0;
  drawChart();
  function drawChart() {
    if (rowIndex < rawData.length) {
      data.addRow(rawData[rowIndex++]);
      chart.draw(data, options);
    }
  }
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
Categories
discuss

recursion causing mutableData.setValue() causing the same activity to be produced in backstack?

Edit: 23/10/2016: This is not solved and I’m still looking for an answer. I am going to rewrite this question to make it clearer as I now know what’s causing this problem.


Edit: 26/10/2016: SOMETHING FOUND: While trying to find the problem, I got a bug that helped me find something .It turns out if I have this in my Firebase database:

Campaigns{
   UNQ_KEY: 1 //This is being set in the transaction
}

Rather than this:

Campaigns{
   UNQ_KEY:{
    count: 1 //this is being set in the transaction
  }
}

The problem doesn’t happen.

So, in conclusion, it’s probably a recursion error.


I have this Firebase transaction:

database.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            Long preUserIncrementedInt = Long.parseLong(b.getText().toString());
            Long userIncrementedInt = ++preUserIncrementedInt;
            mutableData.child("users").child(getUid()).child("count").setValue(userIncrementedInt);
            Long preIncrementedTotalCount = mutableData.child("count").getValue(Long.class);
            Long incrementedTotalCount = ++preIncrementedTotalCount;
            mutableData.child("count").setValue(incrementedTotalCount);
            return Transaction.success(mutableData);
        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
            if (databaseError != null)
                Log.wtf(TAG,databaseError.getMessage());
        }
    });

This line:

mutableData.child("users").child(getUid()).child("count").setValue(userIncrementedInt);

and this one:

mutableData.child("count").setValue(incrementedTotalCount);

When I run the transaction, the same activity gets created again and opens. When I click the back button, it goes to the previous activity in the backstack. BUT, the previous activity in the backstack is the same activity itself. Like this:

IMAGE

Each time I click the button, a new activity (activity with the problem) is produced in the backstack.

To show you how it looks like, here’s a GIF:

GIF

Why is this happening?

Answer

(I will be posting here as its easier to manage my comments)…

The solution is NOT found.

*UPDATE 4: Solution Found**

After many tries, and lots of comments, the solution was finally found, apparently the OP had the increment method in another class and moving it to the same class it was being used on solved the issue.

As of why this might happened, in my opinion, maybe it had to do with a concurrency issue on the transaction, maybe the problem was that it was creating a cycle on its own. Your activity starts, later you instantiated your FirebaseController which, at some point, fired off the increment method, making an async execution which ends up (failing in some way?) and that starts your activity again



See below for failed (but troubleshooting steps) attempts


I tried to debug. It wasn’t activated on any of these lines. It takes me to a bunch of Android files (such as View.java). When I “Run to cursor” (skip the next debug breakpoint), it restarts.

Can you try to check whether the clicked view inside the runnable is not null ?

Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // if not null do this
            clicked.setEnabled(true);
            // if null print some log
            // ...
        }
    };

Are you using Step Into or Step over when debugging (if you get deeper in the hierarchy of classes you might be using Step Into (F5), can you try debugging with Step Over (F6) )?

If we found the answer I will post it here:

UPDATE 1:

MutableData#setValue(java.lang.Object) The documentation explains how this works:

Set the data at this location to the given value. The native types accepted by this method for the value correspond to the JSON types:

Boolean
Long
Double
Map<String, Object>
List<Object>

In addition, you can set instances of your own class into this location, provided they satisfy the following constraints:

The class must have a default constructor that takes no arguments The class must define public getters for the properties to be assigned. Properties without a public getter will be set to their default value when an instance is deserialized

Try using another datatype as suggested by fellow developers:

change the #setValue parameter to an object of the list above and #getValue also return an object, try to cast to the correct type, maybe you could use Integer class

UPDATE 2:

Does your data schema look something like this?

{
    "campaings": {
        "key": {
            "count": "1",
            "users": {
                "-JRHTHaIs-jNPLXOQivY": {
                    "count": "1",
                    ...
                },
                ...
            }
            ...
        },
        "other-key": {
            ...
        }
        ...
    }
}

Thats what I infer from the pieces of code there, you can clarify me if I made a mistake.

// here we are searching for the current reference in Campaings/key
DatabaseReference database = FirebaseDatabase.getInstance().getReference().child("Campaigns").child(key);

int preIncrementUserCount = Integer.parseInt(button.getText().toString());
final int incrementedUserCount = ++preIncrementUserCount;

button.setText(String.valueOf(incrementedUserCount));
database.runTransaction(new Transaction.Handler() {
    @Override
    public Transaction.Result doTransaction(MutableData mutableData) {

        // here we are searching for the current count value in 
        // Campaings/key/count
        Integer currentValue = mutableData.child("count").getValue(Integer.class);

        if (currentValue == null) {
            // do something...
        } else {
            // here we are setting the count value in Campaings/key/count
            mutableData.child("count").setValue(++currentValue);
        }

        // here we are setting the count value in Campaings/key/users/UUID/count
        mutableData.child("users").child(getUid()).child("count").setValue(incrementedUserCount);

        return Transaction.success(mutableData);
    }

    @Override
    public void onComplete(DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) {

       if (databaseError != null) {
            Log.e(TAG, "Error: " + databaseError.getMessage());
       }

       System.out.println("Transaction completed");
    }
});

The point of the code example is to illustrate the data schema searches you are doing (again, correct me in any part if I made a mistake), but please put the databaseError log on onComplete for debugging purposes

UPDATE 3

From the documentation:

doTransaction() will be called multiple times and must be able to handle null data. Even if there is existing data in your remote database, it may not be locally cached when the transaction function is run.

Try changing this part:

  if (currentValue == null) {
      // do something...
  } else {
      // here we are setting the count value in Campaings/key/count
      mutableData.child("count").setValue(++currentValue);
  }

To something like:

  if (mutableData.child("count").getValue() == null) {
      // print something...
      // Log.d(TAG,"Value at some point was null");
      // or maybe (just to test)
      // mutableData.child("count").setValue(1);
  } else {
      // here we are setting the count value in Campaings/key/count
      mutableData.child("count").setValue(++currentValue);
  }

P.S: I’m leaving the solutions if any person in the foreseable future might be troubleshooting something similar like this

Categories
discuss

How to get the text of multiple elements split by delimiter using jQuery?

I am using jQuery to get the text value of multiple td elements in a row:

var getText = $(this).closest("tr").text();

The value of getText ends up being one long concatenated string of the text of each element with no breaks. Is it possible to add a delimiter for each new td element that it gets the text value from?

Answer

I’d first suggest retrieving an Array of the cells’ text, rather than a single String:

var cellTexts = $(this).closest("tr").find('td').map(function(){
                  return $(this).text();
                }).get();

If you wish to have a single string, with a custom delimiter, you can then call Array.prototype.join(), and specify the delimiter you wish to use, for example a comma:

var cellTexts = $(this).closest("tr").find('td').map(function(){
                  return $(this).text();
                }).get(),
    allText = cellTexts.join(',');

References:

Categories
discuss

Session design of an Application server API with multiple client platforms

I’d like to build an app that’ll support multiple platforms: Desktop applications (Mac/PC), Web (angularJS fronted) and native mobile apps.

So I’m thinking of an application server, serving internal APIs to the platforms above. I have certain assumptions regarding how login/logouts are to be supported. I would be happy if anyone could comment if my thinking is wrong.

  1. For desktop and mobile apps, the “login” function will use the internal API to communicate the credentials and in return will receive a permanent token. the desktop/mobile app will store the token and use it with any subsequent request to the application server. Upon “logout” from the desktop/mobile app, the token will be discarded on the server side an forgotten on the front end app side.
  2. For the web interface, the angular application will retain the token provided after login as a cookie and will load it up and use it with any request made to the application server.

Is this a common pattern?

Answer

You have the basic structure correct, however with OAuth2 you will never be storing the access token forever. The access token is often an opaque string that grants access to your API, storing it in a cookie or local storage is fine, but issuing a token from the server that never expires would be highly inadvisable (a MITM attack could jack your identity forever).

To solve this issue, OAuth2 implementations typically dole out refresh tokens alongside access tokens. A refresh token will typically have a longer expiration timeframe than an access token (anywhere between the expiration time of the access token and a month I would say). Refresh tokens are akin to a temporary user password – they do not grant any access to your API directly, however with one a user can authorize with your system via calling your OAuth2 refresh api, and get back fresh access and refresh tokens with new expiration time. This gives your application a chance to revalidate the users claims regularly (maybe their access / role has changed and they need updated claims).


JWT Tokens

Access tokens may be opaque strings that you store on the server, however I would highly recommend using JWT tokens. JWT tokens have 2 major benefits over opaque (meaningless) tokens:

1. Client Claims

The first thing you are going to need to do in your client application post-authorization is look up all kinds of stuff to build your UI. The beauty of JWT tokens is that they store all of your users claims (including your apps custom user claims) as a JSON object payload inside an encoded string which can be decoded client-side by first splitting the token on ., which breaks it into [ header, payload, sig ] base 64 encoded strings. You can then base 64 decode the payload string and run it through JSON.parse which will produce your claims key-value pairs:

const access_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ'
const claims = JSON.parse(atob(access_token.split('.')[1]))
console.info(claims)

This allows your client application to decode the users claims atomically from nothing more than an access token vs. the traditional model of using the access token to go and look up information about the user. With JWT you will immediately know the users first name, last name, user ID, and any other data you would like to stick in the JWT token.

2. Sessionless

To use your authorized API, your client application will make requests to endpoints and send an 'Authorization': 'Bearer access_token' (where access_token is your access token). In traditional apps, the access token must be looked up server side to verify that the server granted it. The other awesome bit about JWT tokens is that when they are issued there is a server side secret that is used to sign them. When the server needs to verify them it simply uses the server side secret to sign them and if it passes, the server will grant the API request based on the claims of the decoded token. There is no need to store them server side making your architecture much simpler. The server has no need to talk to a database on every authorized API request. You will be bypassing many issues such as synchronizing access tokens across web farms or storing them at all (you will however still need to store the refresh tokens in a table linked to the user).


Cookies vs. Local Storage

A pretty common misconception people have about cookies is that they should be avoided because they open you up to CSRF attacks, however this is often not the case. Systems like web forms that send session cookies and hydrate session based on those cookies are open to CSRF attacks but if you are building a single page application and all of your security checkpoints are at your API layer, your endpoints will be checking the Authorization header for your bearer token, not the cookies. If you are doing server side rendering and using the cookies value there, you should be aware of CSRF threats and implement methods of prevention. If you go with cookies, you should ensure they do not have the HttpOnly flag set and do have the Secure flag set to protect you from MITM threats.


Since you are using node (or angular at least), I will now plug a library I wrote – jwt-autorefresh. The point of this library is simple, give it your apps refresh mechanism (the client code that makes the http request to your refresh api and subsequently stores results in a cookie) and the number of seconds that you want to have your tokens refreshed prior to their expiration, and it will handle auto scheduling refresh on your client application. Internally it decodes your JWT token and looks at its exp claim (expiration time) to figure out how far out it needs to schedule your refresh. It has features such as adding a small amount of jitter to the refresh time so that all client instances will not attempt refreshing simultaneously.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..