0

I'd try somewhere like Microcenter, if you look at their clearance/open box section on the website there are some deals to be had. I don't know what your budget is, but this for $791 looks like it'll fit the bill. You'd have to see what's available in your local store though!

There seems to be a bit of anti-Dell rhetoric in here, but the XPS range is good, I prefer my XPS 13 over my MBP in some ways.

-1

True, and if she wants to continue and learn then fair play, and I hope she manages to build something great.

However, she's using a discontinued tool that outputs unmaintainable HTML, and developing her site clearly isn't her goal; letting people know about her jewelry (which looks fantastic, by the way Sanda) is.

Plus, as there's a products tab on her site, one would expect that some kind of 'web shop' is on the radar. That won't be doable in Webplus, and it's not the easiest thing to implement from scratch at the best of times.

-1

I'd suggest using something like SquareSpace for this kind of site, rather than attempting to build it yourself. It has an e-commerce module built-in and plenty of easy templates to choose from.

A note unrelated to the original question, when at 100% zoom, I can only see 2/3 of the page, I need to scroll right to see the whole thing (or zoom out to about 80%).

2

I've been following this with some interest. Bad practice to end with a verb?

I think the distinction is between an API and a web app. In a web app, /widgets/123/edit (obtained via a GET) should contain a form that allows you to edit Widget number 123. Submitting the form should send aPATCH to /widgets/123.

In the case of an API, you don't need an edit form so you can omit verbs from the route entirely.

0

It turned out that the load balancer was blocking non-GET/POST requests. It wasn't an Nginx problem after all!

This doesn't suprise me at all! :)

I actually imitated the /users/~ endpoint after LinkedIn's API, which does:

Yes, but LinkedIn's API is read only.

If Dazah's API allows you to update your profile then it definitely makes sense to split it. Allowing PUT or PATCH to work if the :user_id param is ~ but not if it's anything else adds inconsistency to the API and will add to the complexity either in your code or in your documentation.

Also, because the returned data probably differs despite having the same endpoint (as you expect to see a bit more data on your own profile compared to someone else's), the API in general is less predictable than if you used two disparate endpoints for interacting with profiles generally and viewing/modifying your own.

2

It would appear that too many notifications are added to the feed for certain events, making it difficult to sort the wheat from the chaff.

Take the example of this annoying spammer creating a post:

Screen_Shot_2017-01-26_at_15_16_46.png

Aside from the fact he's a waste of oxygen, that's more than one whole screen of notifications for a post creation and quick edit (less than a minute after posting). Also, I don't see any replies, so perhaps the "replied to a post" notification is superflouous. Perhaps these could be condensed; do we need to know who started watching each post - it might make more sense to display that on the post page; "being watched by..."

Votes + Comments
That and now I want a Black Mirror "Block" mode.
0

What if I want to modify the third party module? Where can I find it?

pip show unidecode

Metadata-Version: 2.0
Name: Unidecode
Version: 0.4.20
Summary: ASCII transliterations of Unicode text
Home-page: UNKNOWN
Author: Tomaz Solc
Author-email: tomaz.solc@tablix.org
Installer: pip
License: GPL
Location: /usr/local/lib/python2.7/site-packages
Requires:
Classifiers:
  License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
  Programming Language :: Python
  Programming Language :: Python :: 2
  Programming Language :: Python :: 3
  Topic :: Text Processing
  Topic :: Text Processing :: Filters
Entry-points:
  [console_scripts]
  unidecode = unidecode.util:main

And, if the only way is installing the module, why should a software provide the module files? Does it mean there is a way of installing a module when you have its code?

The answers to these questions and more can be found in one of thousands of Python tutorials, manuals, books and instructional videos online.

1

D3 isn't the correct choice for in this situation; it's aimed at visualisation (as per the request in the original post). If you want to interact with scales by dropping different-weighted balls on them in anything but the simplest of interfaces, you need a physics engine. Matter-JS provides this and makes it really simple to get fantastic results.

Votes + Comments
Wow! matter.js is cool :)
0

Regarding PUT and PATCH, I looked and looked, and was unable to find a working tutorial on how to implement them in Nginx. Everything I read said that Nginx does not have support??

Hmm, @cereal's script works for me using NGINX 1.10.2 with a pretty standard config and PHP 7.0.14

http --form PUT http://localhost:8080/test.php msg="hello" --verbose
PUT /test.php HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 9
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: localhost:8080
User-Agent: HTTPie/0.9.2

msg=hello

HTTP/1.1 200 OK
Connection: keep-alive
Content-Type: text/html; charset=UTF-8
Date: Thu, 26 Jan 2017 10:07:03 GMT
Host: localhost:9000
Server: nginx/1.10.2
Transfer-Encoding: chunked
X-Powered-By: PHP/7.0.14

Method PUT
Array
(
    [msg] => hello
)
0

I guess my question to you is, from a routing perspective, why would /users/([0-9]+) (essentially users/ followed by a positive integer) be confused with /users/~ (users/ followed by a tilde), but not be confused with /users/searches or /users/nearby??

I'd say in a 'pure' world, yes. If, as a user, I can only update their own profile (and not anyone else's), and they only have one of them, why is /users in the path at all? Also, Unix folk will know that ~ is 'home', but other people wont. The URL, which is a legitimate part of the UI, isn't as descriptive or friendly as it could be.

It also means that you need to pay extra attention to the order in which your routes are applied (same applies to /users/searches and /users/nearby). This can be a bigger headache if you're using slugs; what happens if a user called 'searches' registers? It's very simple with a few (or a few dozen) endpoints. I've seen some monstrosities in the past and ensuring the ordering is correct becomes very complicated indeed.

There's no right and wrong here. If you're happy with the /users/~ route and there's nothing that will have an impact on its functionality, go with it. From the consumer point of view, so long as it's obvious what's going on and there's some documentation (or better yet, a client library that does it for you), it should be fine.

1

Regarding PUT and PATCH, I looked and looked, and was unable to find a working tutorial on how to implement them in Nginx. Everything I read said that Nginx does not have support??

NGINX definitely supports them, as far as I know you don't need to enable anything. It should just work.

I just wrote (well, copied, pasted and amended) a tiny app in PHP (the first time I've ever tried PHP!) and it handled PUT like a boss.

0

Sorry if I didn't make it clear. When I refer to 'additional logic', I mean checking that the API's response is suitable for the user making the request.

There are two scenarios in your example, generally listing and viewing user profiles and viewing and modifying your own profile. It makes sense from an API point of view and a code-organisation point of view to split these between two controllers. Requests to /users/20 and /users/~ will be routed to the same place (by every router I've worked with, at least!), because the paths match; the only difference is the parameter on the end (20 vs ~). This means you'd need additional code to cope with the params and react accordingly.

To attempt to clarify what I mean, here's a quick example of how a single controller that's trying to perform both roles might look. Note how inside #update and #show, there's additional logic that makes the controller more difficult to understand because it no longer has a single responsibility.

If we split that functionality into two, we have two simple controllers; the user controller that only provides allowed actions and the profile controller that only has access to the currently logged-in user.

If you're also building a web interface on top of (or to compliment) this API, it makes even more sense, because you want to serve a different page for someone visiting their own profile vs visiting someone elses. Again, it's simpler and cleaner to do this with separate views ...

0

Incidentally, in my previous post the profile's POST line should have been a PUT or PATCH; you'd assume that every user has one and shouldn't be able to create another.

The difference, I guess, is that users/1 returns the results as a collection while users/~ returns a singular resource, us. Is that what you were referring to?

Not exactly. /users/~, or /users/{my_id} is fine for accessing my profile page, but it's also the way you'd access anyone else's profile page.

This approach means you'd need additional logic in the views (and checks in the controller) to display things that only a user can do to themselves, such as modify personal details, update profile picture, view their own event log, etc.

This makes the functionality more difficult to write, test and maintain, because the action isn't specific.

Splitting it out makes both sides simpler.

Also, I agree, /me sounds better than /profile, but /me/cv sounds odd. What is the profile component? Does a user only have one?

There are only two hard things in Computer Science: cache invalidation and naming things. - Phil Karlton

0

For the most part I'd say it looks ok.

The tilde in some of the currently-OAuthed user routes doesn't 'feel' right to me, though. The current user (or you), and the current user's CV (your CV) are both singular resources; you already know their ID if they are authenticated so you needn't treat them as if they are a collection:

GET  profile
POST profile
GET  profile/cv
POST profile/cv
1

I use snippets heavily. For non-work stuff, Github's gists are perfect. You can add multiple files to a single gist (which would help if some of the code you're pasting is spread across a model, controller and view), and everything's syntax highlighted.

Github allows gists to be embedded. Perhaps this would be a better approach than creating one from scratch. To build anything with that kind of functionality that people will actually want to use is a project in itself.

0

So two things are happening here, first you're searching for a row and if you find one, you're updating the timestamp (and if not, doing an insert). It's unlikely that it's the insert that's slow, so let's check the query first:

explain select *
from articles_read
where member_id = 314062
and article_id = 507257;

The output should indicate whether or not your index is being used. If it's not, you need to look at why. If it is, then it might indiacate that the update (or insert) is slow. I suspet it's the former, so try the above and if that's not the problem we can look in more depth at the inserting/updating

0

To clarify, I think @jkon was making a joke. SOAP was a nightmare at the best of times and unusable at the worst, and I'm glad I've not had to deal with WSDL in years.

Keeping an interface simple, RESTful and documenting it with Swagger or Stoplight is a much better idea.

1

I'm no PHP expert, so forgive my ignorance.

If you test in a basic manner, rather than by using AJAX, what happens? By using your browser's inspector, you can see that doing:

$.ajax({
  url: "my_service",
  data: {f_date1: "yesterday", t_date1: "today"},
  success: function(msg) {
    console.debug("yay")
  }
});

will result in a GET request like this:

my_service?f_date1=yesterday&t_date1=today

If you paste that into a browser's URL bar (or better yet use something like HTTPie or Postman), you can make sure that you can access the query string properly. Once you know that works, and you know that jQuery's .ajax method does the same thing, you'll have a much better chance at solving your problem.